var net = require('net');
var fs = require('fs')

// data model
function IP(opt) {
    opt = opt || {};

    this._database = opt.database || fs.readFileSync('app/data/data.dat');
    this._index = opt.index || require('../data/index');

    console.log("Data Init Complete!");
}

//private method for ip 2 int
function ip2int(ip) {
    var ipInt = 0;
    if (typeof ip === "number") {
        ipInt = ip;
    } else if(ip.indexOf(':') != -1) {
        ip = ip.split(":").pop();
    }

    if(net.isIPv4(ip)) {
        ipInt = ip.split('.').reverse()
            .map(function(v, i) {return v << (i * 8);})
            .reduce(function(a, b) {return a+b;}) >>> 0;
    }

    if (isNaN(ipInt) || ipInt <= 0 || ipInt > 0xFFFFFFFF) {
        throw new Error('invalid ip address');
    }

    return ipInt;
}

// lookup method
IP.prototype.lookup = function (ip) {
    var ipInt = ip2int(ip);

    var ipIndex = parseInt(ipInt / (1 << 24));
    var floot = this._index[ipIndex - 1];
    var ceil = this._index[ipIndex];

    function getItem(data, index) {
        var buf = new Buffer(240);

        try {
            data.copy(buf, 0, 240 * index, 240 * (index + 1));
        } catch (err) {
            return {"_des" : "保留地址"};
        }
        // why \u0000 in the buf string?
        return JSON.parse(buf.toString().replace(/\u0000/g, ''));
    }

    // binary search
    while(floot <= ceil) {
        var middle = parseInt((floot + ceil) / 2);

        var midItem = getItem(this._database, middle);
        if (midItem._ip < ipInt) floot = middle + 1;
        else if (midItem._ip > ipInt) ceil = middle - 1;
        else {
            return midItem;
        }
    }

    return getItem(this._database, floot);
}

module.exports = IP;